import 'dart:convert';
import 'dart:typed_data';

import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:sp_util/sp_util.dart';
import 'package:sprintf/sprintf.dart';
import 'package:xiongmao_clean_flutter_module/net/http_config.dart';
import 'package:xiongmao_clean_flutter_module/util/log_utils.dart';

import '../res/constant.dart';
import '../util/device_utils.dart';
import 'error_handle.dart';

class AuthInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    final String accessToken = SpUtil.getString(Constant.accessToken) ?? httpConfig.token;
    if (accessToken.isNotEmpty) {
      options.headers['Authorization'] = 'token $accessToken';
    }
    if (!Device.isWeb) {
      // https://developer.github.com/v3/#user-agent-required
      options.headers['User-Agent'] = 'Mozilla/5.0';
    }
    super.onRequest(options, handler);
  }
}

class SignInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    var params = Map<String, dynamic>();
    if (options.data != null && options.data is Map) {
      params = options.data;
    }
    if (options.headers == null) {
      options.headers = Map<String, String>();
    }

    params["xmjz_time"] = (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString();

    options.queryParameters.addAll({"xmjz_time": params["xmjz_time"]});
    params.addAll(options.queryParameters);

    options.headers["xmjztoken"] = httpConfig.token;
    options.headers["xmjzversion"] = httpConfig.version;
    options.headers["xmjzdevice"] = httpConfig.device;
    options.headers["xmjzplatform"] = defaultTargetPlatform == TargetPlatform.iOS ? "IOS" : "Android";
    options.headers["xmjzsign"] = _createSign(options.path, options.headers["xmjztoken"], params);
    // options.headers["xmjzsign"] = "6efc282b199188b783d088915e7608ea";
    print(" 签名 = ${options.headers}");
    super.onRequest(options, handler);
  }

  static String createSign(String url, String token, Map<String, dynamic> params) {
    return _createSign(url, token, params);
  }

  /// 生成请求签名
  static _createSign(String url, String token, Map<String, dynamic> params) {
    String key = "szd0djn5yMc8weWi";
    if (params == null) {
      return null;
    }

    if (url.isEmpty) {
      //throw new NullPointerException("Request Url must not be null!");
      return null;
    }
    Map<String, String> signParams = Map.from(params);
    signParams["xmjz_url"] = url;
    List<String> keys = List.from(signParams.keys);
    keys.sort((left, right) => left.compareTo(right));

    String text = "";
    for (int index = 0; index < keys.length; ++index) {
      String key = keys.elementAt(index);
      String value = signParams[key] ?? "";
      if (key == 'xmjz_url') {
        String cover = value.replaceFirst("/", "", 0).replaceAll("/", '%2F');
        text += "," + key + "##" + cover;
        MyLog.e("加密之前的内容 xmjz_url -> " + cover);
      } else {
        text += "," + key + "##" + Uri.encodeComponent(value);
      }
    }

    if (text.isEmpty) {
      text += ",";
    }

    MyLog.e("加密之前的内容 " + "token=$token,values=${text.substring(1)}");
    Uint8List content = utf8.encoder.convert("token=$token,values=${text.substring(1)}");
    Digest digest = md5.convert(content);
    String firstString = digest.toString();
    content = utf8.encoder.convert("$firstString,$key");
    digest = md5.convert(content);
    return digest.toString();
  }
}

class LoggingInterceptor extends Interceptor {
  late DateTime _startTime;
  late DateTime _endTime;

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    _startTime = DateTime.now();
    MyLog.e('----------Start----------');
    if (options.queryParameters.isEmpty) {
      MyLog.e('RequestUrl: ${options.baseUrl}${options.path}');
    } else {
      MyLog.e('RequestUrl: ${options.baseUrl}${options.path}?${Transformer.urlEncodeMap(options.queryParameters)}');
    }
    MyLog.e('RequestMethod: ${options.method}');
    MyLog.e('RequestHeaders:${options.headers}');
    MyLog.e('RequestContentType: ${options.contentType}');
    MyLog.e('RequestData: ${options.data.toString()}');
    super.onRequest(options, handler);
  }

  @override
  void onResponse(Response<dynamic> response, ResponseInterceptorHandler handler) {
    MyLog.e('----------request-url--------: ${response.requestOptions.path}');
    _endTime = DateTime.now();
    final int duration = _endTime.difference(_startTime).inMilliseconds;
    if (response.statusCode == ExceptionHandle.success) {
      MyLog.e('ResponseCode: ${response.statusCode}');
    } else {
      MyLog.e('ResponseCode: ${response.statusCode}');
    }
    // 输出结果
    MyLog.json(response.data.toString());
    MyLog.e('----------End: $duration 毫秒----------');
    super.onResponse(response, handler);
  }

  @override
  void onError(DioError err, ErrorInterceptorHandler handler) {
    MyLog.e('----------Error-----------');
    super.onError(err, handler);
  }
}

class AdapterInterceptor extends Interceptor {
  static const String _kMsg = 'msg';
  static const String _kSlash = "'";
  static const String _kMessage = 'message';

  static const String _kDefaultText = '无返回信息';
  static const String _kNotFound = '未找到查询信息';

  static const String _kFailureFormat = '{"code":%d,"message":"%s"}';
  static const String _kSuccessFormat = '{"code":0,"data":%s,"message":""}';

  @override
  void onResponse(Response<dynamic> response, ResponseInterceptorHandler handler) {
    final Response<dynamic> r = adapterData(response);
    super.onResponse(r, handler);
  }

  @override
  void onError(DioError err, ErrorInterceptorHandler handler) {
    if (err.response != null) {
      adapterData(err.response!);
    }
    super.onError(err, handler);
  }

  Response<dynamic> adapterData(Response<dynamic> response) {
    String result;
    String content = response.data?.toString() ?? '';

    /// 成功时，直接格式化返回
    if (response.statusCode == ExceptionHandle.success || response.statusCode == ExceptionHandle.success_not_content) {
      if (content.isEmpty) {
        content = _kDefaultText;
      }
      result = sprintf(_kSuccessFormat, [content]);
      response.statusCode = ExceptionHandle.success;
    } else {
      if (response.statusCode == ExceptionHandle.not_found) {
        /// 错误数据格式化后，按照成功数据返回
        result = sprintf(_kFailureFormat, [response.statusCode, _kNotFound]);
        response.statusCode = ExceptionHandle.success;
      } else {
        if (content.isEmpty) {
          // 一般为网络断开等异常
          result = content;
        } else {
          String msg;
          try {
            content = content.replaceAll(r'\', '');
            if (_kSlash == content.substring(0, 1)) {
              content = content.substring(1, content.length - 1);
            }
            final Map<String, dynamic> map = json.decode(content) as Map<String, dynamic>;
            if (map.containsKey(_kMessage)) {
              msg = map[_kMessage] as String;
            } else if (map.containsKey(_kMsg)) {
              msg = map[_kMsg] as String;
            } else {
              msg = '未知异常';
            }
            result = sprintf(_kFailureFormat, [response.statusCode, msg]);
            // 401 token失效时，单独处理，其他一律为成功
            if (response.statusCode == ExceptionHandle.unauthorized) {
              response.statusCode = ExceptionHandle.unauthorized;
            } else {
              response.statusCode = ExceptionHandle.success;
            }
          } catch (e) {
//            MyLog.e('异常信息：$e');
            // 解析异常直接按照返回原数据处理（一般为返回500,503 HTML页面代码）
            result = sprintf(_kFailureFormat, [response.statusCode, '服务器异常(${response.statusCode})']);
          }
        }
      }
    }
    response.data = result;
    return response;
  }
}
